import CryptoJS from 'crypto-js';//AES
import JSEncrypt from 'jsencrypt';//RSA
import Encrypt from 'encryptlong';//分段加密
import jsrsasign from 'jsrsasign';//加签

const AES_KEY = 'akRHUlhVU3FrUnVx';
const IV = 'E08ADE2699714B87';

const crypto = {
  /**
   * AES之CBC模式加解密
   * 需要key，iv和文本
   */
  // base64格式 【加密】
  encryptCBCbase64: (word) => {
    const key = CryptoJS.enc.Utf8.parse(AES_KEY);
    const text = CryptoJS.enc.Utf8.parse(word);
    const encrypted = CryptoJS.AES.encrypt(text,key, {
      iv: CryptoJS.enc.Utf8.parse(IV),
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7}
    );
    return encrypted.toString();
  },
  // base64格式 【解密】
  decryptCBCbase64: (word) => {
    const key = CryptoJS.enc.Utf8.parse(AES_KEY);
    const decrypt = CryptoJS.AES.decrypt(word, key, {
      iv: CryptoJS.enc.Utf8.parse(IV),
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7}
    );
    return CryptoJS.enc.Utf8.stringify(decrypt).toString();
  },
  // Hex格式 【加密】
  encryptCBChex: (word) => {
    const key = CryptoJS.enc.Utf8.parse(AES_KEY);
    const text = CryptoJS.enc.Utf8.parse(word);
    const encrypted = CryptoJS.AES.encrypt(text,key, {
      iv: CryptoJS.enc.Utf8.parse(IV),
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7}
    );
    // return encrypted.ciphertext.toString();
    return encrypted.ciphertext.toString().toUpperCase();   //  字母全部大写
  },
  // Hex格式 【解密】
  decryptCBChex: (word) => {
    const key = CryptoJS.enc.Utf8.parse(AES_KEY);
    const text = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(word));
    const decrypt = CryptoJS.AES.decrypt(text, key, {
      iv: CryptoJS.enc.Utf8.parse(IV),
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7}
    );
    return CryptoJS.enc.Utf8.stringify(decrypt).toString();
  },

  /**
   * AES之ECB模式加解密
   * 只需要key和文本
   */
  // base64格式 【加密】
  encryptECBbase64: (word) => {
    const text = CryptoJS.enc.Utf8.parse(word);
    const key = CryptoJS.enc.Utf8.parse(AES_KEY);
    const encrypted = CryptoJS.AES.encrypt(text, key, {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7
    })
    return encrypted.toString();
  },
  // base64格式 【解密】
  decryptECBbase64: (word) => {
    const key = CryptoJS.enc.Utf8.parse(AES_KEY);
    const decrypt = CryptoJS.AES.encrypt(word, key, {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7
    })
    return CryptoJS.enc.Utf8.stringify(decrypt).toString()
  },
  // hex格式 【加密】
  encryptECBhex: (word) => {
    const text = CryptoJS.enc.Utf8.parse(word);
    const key = CryptoJS.enc.Utf8.parse(AES_KEY);
    const encrypted = CryptoJS.AES.encrypt(text, key, {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7
    })
    return encrypted.ciphertext.toString();
  },
  // hex格式 【解密】
  decryptECBhex: (word) => {
    const text = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(word));
    const key = CryptoJS.enc.Utf8.parse(AES_KEY);
    const decrypt = CryptoJS.AES.encrypt(text, key, {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7
    })
    return CryptoJS.enc.Utf8.stringify(decrypt).toString()
  },

  /**
   * 生产随机字符串
   * @param min
   * @param max
   * @returns {string}
   */
  generateRandomCode: (min = 16, max = 16) => {
    const charset = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
    const range = Math.round(Math.random() * (max - min)) + min;
    let randomCode = '';
    for (let i = 0; i < range; i++) {
        randomCode += charset[Math.round(Math.random() * (charset.length - 1))];
    }
    return randomCode;
  },

  /**
   * RSA 公钥加密
   * @param plainText
   * @param key
   */
  encryptByRSA (plainText, key) {
    const encrypt = new JSEncrypt(); // 实例化加密对象
    encrypt.setPublicKey('-----BEGIN PUBLIC KEY-----' + key + '-----END PUBLIC KEY-----'); // 设置公钥
    return encrypt.encrypt(plainText); // 加密返回
  },

  /**
   * RSA 私钥解密
   * @param plainText
   * @param key
   */
  decryptByRSA (plainText, key) {
    const decrypt = new JSEncrypt(); // 实例化加密对象
    decrypt.setPrivateKey('-----BEGIN RSA PRIVATE KEY-----' + key + '-----END RSA PRIVATE KEY-----'); // 设置私钥
    return decrypt.decrypt(plainText);
  },

  /* JSEncrypt加密 */
  rsaPublicData: (data, publicKey) => {
    const jsencrypt = new JSEncrypt()
    jsencrypt.setPublicKey(publicKey)
    // 如果是对象/数组的话，需要先JSON.stringify转换成字符串
    var result = jsencrypt.encrypt(data)
    return result
  },
  /* JSEncrypt解密 */
  rsaPrivateDat: (data, priKey)  => {
    const decrypt = new JSEncrypt()
    decrypt.setPrivateKey(priKey);
    // 如果是对象/数组的话，需要先JSON.stringify转换成字符串
    var result = decrypt.encrypt(data)
    return result
  },

  // 分段加密
  encrypt (data, publicKey) {
    var encryptor = new Encrypt()
    encryptor.setPublicKey(publicKey)
    // 如果是对象/数组的话，需要先JSON.stringify转换成字符串
    const result = encryptor.encryptLong(data)
    return result
  },
  // 分段解密 - privateKey验证
  decrypt (data, privateKey) {
    var encryptor = new Encrypt()
    encryptor.setPrivateKey(privateKey)
    // 如果是对象/数组的话，需要先JSON.stringify转换成字符串
    var result = encryptor.decryptLong(data)
    return result
  },
  // 私钥加签
  signature (signData, privatekey) {
    let rsa = new jsrsasign.RSAKey();
    rsa = jsrsasign.KEYUTIL.getKey('-----BEGIN PRIVATE KEY-----' + privatekey + '-----END PRIVATE KEY-----');
    let sig = new jsrsasign.KJUR.crypto.Signature({"alg": "SHA1withRSA", "prov": "cryptojs/jsrsa"});
    sig.init(rsa);
    sig.updateString(signData); // 加签
    let sign = jsrsasign.hextob64(sig.sign());
    return sign;
  },
  // 验签 用公钥对签名进行验签
  verify (signData, ciphertext, publicKey ) {
    // signData: 加签的数据
    // ciphertext : 加签之后得到的签文
    let key = '-----BEGIN PUBLIC KEY-----' + publicKey + '-----END PUBLIC KEY-----';
    let sig = new jsrsasign.KJUR.crypto.Signature({"alg": "SHA1withRSA", "prov": "cryptojs/jsrsa", prvkeypem: key});
    sig.updateString(signData);
    let result = sig.verify(jsrsasign.b64tohex(ciphertext));
    return result;
  },
};

export default crypto;
